package org.example.oop.io_stream;

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * org.example.oop.stream
 *
 * @author moLei
 * @description 解压缩流，java中只能识别zip压缩
 * @since 2025/6/20
 */
@Slf4j
public class ZipStreamDemo01 {

    private static final String dest = "test.zip";

    private static final String src = "test";

    /**
     * 解压缩
     */
    public static void unZip() {
        // 获取需要解压缩的压缩包
        try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(dest))) {

            // 获取压缩包中的文件
            ZipEntry zipEntry;
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                // 获取文件名，zipEntry对象的name是保持目录结构和文件名称的：test/test1.txt这种结构
                String name = zipEntry.getName();
                // 判断文件是否为文件夹
                if (zipEntry.isDirectory()) {
                    // 创建文件夹
                    new File(name).mkdirs();
                } else {
                    // 不是文件夹，是文件，将文件放入指定位置
                    try (FileOutputStream fileOutputStream = new FileOutputStream(name)) {
                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = zipInputStream.read(bytes)) != -1) {
                            fileOutputStream.write(bytes, 0, len);
                        }
                    }
                }

            }
        } catch (Exception e) {

        }
    }

    /**
     * 压缩包中的每一个文件都是zipEntry对象
     */
    public static void zip() {
        // 获取压缩流对象
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest))) {
            // 获取压缩包的输出流，使用递归将文件夹下的所有文件压缩进入压缩包内
            recursionReadFile(src, zos);
        } catch (Exception e) {
            log.error("文件操作异常：{}", e.getMessage(), e);
        }
    }

    /**
     * 递归读取文件放入压缩包中
     * @param fileName
     */
    public static void recursionReadFile(String fileName, ZipOutputStream zos) throws IOException {
        // 创建文件
        File file = new File(fileName);
        if (file.isDirectory()) {
            // 先将该文件夹压缩进入压缩包中
            ZipEntry zipEntry = new ZipEntry(fileName + "/");
            zos.putNextEntry(zipEntry);
            // 是文件夹，判断下面是否还有文件
            File[] files = file.listFiles();
            if (files != null && files.length > 0) {
                for (File f : files) {
                    // 进行递归
                    recursionReadFile(fileName + File.separator + f.getName(), zos);
                }
            }
        } else {
            // 文件不是文件夹，是文件，直接将其压缩进入压缩包内
            ZipEntry zipEntry = new ZipEntry(fileName);
            zos.putNextEntry(zipEntry);
            // 将数据写入压缩包内
            FileInputStream fis = new FileInputStream(fileName);
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = fis.read(bytes)) != -1) {
                zos.write(bytes, 0, len);
            }
            // 关闭当前文件的流
            zos.closeEntry();
        }
    }

    public static void toZip(File src, ZipOutputStream zos, String name) throws IOException {
        File[] files = src.listFiles();

        for (File file : files) {
            if (file.isFile()) {
                ZipEntry entry = new ZipEntry(name + File.separator + file.getName());
                zos.putNextEntry(entry);
                FileInputStream fis = new FileInputStream(file);
                int b;
                while ((b = fis.read()) != -1) {
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            } else {
                toZip(file, zos, name + File.separator + file.getName());
            }
        }
    }

    public static void heiMaToZip() throws Exception {
        File srcFile = new File(src);
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
        toZip(srcFile, zos, srcFile.getName());
        zos.close();
    }


    public static void main(String[] args) throws Exception {
        // 初始化需要压缩的文件数据
        // initFiles();

        // 对文件进行压缩
        // zip();
        // 无法压缩空文件夹
        // heiMaToZip();
        // 对压缩包进行解压
        // unZip();

    }

    /**
     * 初始化创建需要压缩的文件数据
     */
    private static void initFiles() {
        File file = new File(src);
        file.mkdirs();
        for (int i = 0; i < 10; i++) {
            if (i % 3 == 0) {
                String pathName = "test//test" + i;
                // 创建文件夹
                new File(pathName).mkdirs();

                // 创建文件，并且初始化值
                try (FileOutputStream fos = new FileOutputStream(pathName + File.separator + "test" + i + ".txt")) {
                    fos.write(("hello world " + i).getBytes());
                } catch (Exception e) {
                    log.error("文件操作异常：{}", e.getMessage(), e);
                }
            } else {
                // 创建文件，并且初始化值
                try (FileOutputStream fos = new FileOutputStream("test//test" + i + ".txt")) {
                    fos.write(("hello world " + i).getBytes());
                } catch (Exception e) {
                    log.error("文件操作异常：{}", e.getMessage(), e);
                }
            }
        }
    }
}
